﻿using UnityEngine;
using System.Collections;

public enum MirrorDir
{
    X,
    Y,
    Z
}

public enum RendererMode
{
    Opaque,
    Cutout,
    Fade,
    Transparent,
}

public class MeshMirrorText : MonoBehaviour 
{
    /// <summary>
    /// 镜像方向
    /// </summary>
    public MirrorDir m_mirrorDir;

    /// <summary>
    /// 镜像与对象距离
    /// </summary>
    public float m_mirrorDis=2.0f;

    /// <summary>
    /// 镜像材质透明度
    /// </summary>
    [Range(0.1f, 1.0f)]
    public float m_mirrorMaterialAlpha = 0.5f;
 
    /// <summary>
    /// 镜像材质颜色
    /// </summary>
    public Color m_mirrorMaterialColor = Color.white;

	// Use this for initialization
	void Start () 
    {
        GenerateMirror();
	}


    private void GenerateMirror()
    {
        if (GetComponent<MeshFilter>() == null && GetComponent<MeshRenderer>() == null)
        {
            Debug.Log("没有找到MeshFilter或MeshRenderer组件");
        }

        GameObject mirror = new GameObject("Mirror");
        mirror.transform.position = this.transform.position;
        mirror.transform.rotation = this.transform.rotation;
        mirror.transform.localScale = this.transform.localScale;

        mirror.transform.SetParent(this.transform);

        mirror.AddComponent<MeshFilter>();
        mirror.AddComponent<MeshRenderer>();

        //镜像的网格
        Mesh mesh = new Mesh();
        mesh.Clear();
        mesh.vertices = GenerateVertices(GetComponent<MeshFilter>().mesh.vertices);
        mesh.triangles = GenerateTriangles(GetComponent<MeshFilter>().mesh.triangles);
        mesh.uv=GetComponent<MeshFilter>().mesh.uv;
        mesh.name = "mirror";
        //重新计算发现(刷新显示)
        mesh.RecalculateNormals();

        mirror.GetComponent<MeshFilter>().mesh = mesh;
        mirror.GetComponent<MeshRenderer>().material = GenerateMaterial(GetComponent<MeshRenderer>().material);
    }

    /// <summary>
    /// 生成镜像顶点
    /// </summary>
    /// <param name="backVertices">原游戏对象的顶点</param>
    /// <returns></returns>
    private Vector3[] GenerateVertices(Vector3[] backVertices)
    {
        Vector3[] newVertices = backVertices;

        switch(m_mirrorDir)
        {
            case MirrorDir.X:
                for (int i = 0; i <= newVertices.Length - 1;i++ )
                {
                    newVertices[i].x = newVertices[i].x * -1 + m_mirrorDis;
                }
                break;
            case MirrorDir.Y:
                for (int i = 0; i <= newVertices.Length - 1; i++)
                {
                    newVertices[i].y = newVertices[i].y * -1 + m_mirrorDis;
                }
                break;
            case MirrorDir.Z:
                for (int i = 0; i <= newVertices.Length - 1; i++)
                {
                    newVertices[i].z = newVertices[i].z * -1 + m_mirrorDis;
                }
                break;
            default:
                break;
        }

        return newVertices;
    }



    /// <summary>
    /// 生成镜像三角面
    /// </summary>
    /// <param name="backTriangles">各个顶点的渲染顺序</param>
    /// <returns></returns>
    int[] GenerateTriangles(int[] backTriangles)
    {
        int[] newTriangles = new int[backTriangles.Length];
        //将所有面的顶点渲染顺序颠倒
        for (int i = 0; i < newTriangles.Length; i++)
        {
            newTriangles[newTriangles.Length - i - 1] = backTriangles[i];
        }

        return newTriangles;
    }

    private Material GenerateMaterial(Material backMeterial)
    {
        Material newMaterial = new Material(backMeterial);
        //不透明
        if (m_mirrorMaterialAlpha >= 1.0f)
        {
            SetMaterialRenderingMode(newMaterial, RendererMode.Opaque);
            if (newMaterial.HasProperty("_Color"))
            {
                newMaterial.SetColor("_Color", m_mirrorMaterialColor);
            }
        }
        //透明
        else
        {
            SetMaterialRenderingMode(newMaterial, RendererMode.Fade);
            if (newMaterial.HasProperty("_Color"))
            {
                m_mirrorMaterialColor.a = m_mirrorMaterialAlpha;
                newMaterial.SetColor("_Color", m_mirrorMaterialColor);
            }
        }

        return newMaterial;
    }


    /// <summary>
    /// 设置纹理渲染模式
    /// </summary>
    /// <param name="material"></param>
    /// <param name="renderingMode"></param>
    private void SetMaterialRenderingMode(Material material, RendererMode renderingMode)
    {
        switch (renderingMode)
        {
            case RendererMode.Opaque:
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                material.SetInt("_ZWrite", 1);
                material.DisableKeyword("_ALPHATEST_ON");
                material.DisableKeyword("_ALPHABLEND_ON");
                material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                material.renderQueue = -1;
                break;
            case RendererMode.Cutout:
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                material.SetInt("_ZWrite", 1);
                material.EnableKeyword("_ALPHATEST_ON");
                material.DisableKeyword("_ALPHABLEND_ON");
                material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                material.renderQueue = 2450;
                break;
            case RendererMode.Fade:
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                material.SetInt("_ZWrite", 0);
                material.DisableKeyword("_ALPHATEST_ON");
                material.EnableKeyword("_ALPHABLEND_ON");
                material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                material.renderQueue = 3000;
                break;
            case RendererMode.Transparent:
                material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                material.SetInt("_ZWrite", 0);
                material.DisableKeyword("_ALPHATEST_ON");
                material.DisableKeyword("_ALPHABLEND_ON");
                material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
                material.renderQueue = 3000;
                break;
        }
    }
}
